
/*
 * Copyright 2002-2021 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/*
 *版权所有2002-2021原作者。
 *
 *根据Apache许可证2.0版许可（“许可证”）；
 *除非符合许可证的规定，否则您不得使用此文件。
 *您可以在以下网址获取许可证副本：
 *
 *https://www.apache.org/licenses/LICENSE-2.0
 *
 *除非适用法律要求或书面同意，软件
 *根据许可证进行的分发是在“按原样”的基础上进行的，
 *无任何明示或暗示的保证或条件。
 *有关管理权限的特定语言，请参阅许可证和
 *许可证下的限制。
 */

package org.springframework.scheduling.annotation;

import java.lang.annotation.Annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import org.springframework.context.annotation.AdviceMode;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;

/**
 * Enables Spring's asynchronous method execution capability, similar to functionality
 * found in Spring's {@code <task:*>} XML namespace.
 *
 * <p>To be used together with @{@link Configuration Configuration} classes as follows,
 * enabling annotation-driven async processing for an entire Spring application context:
 *
 * <pre class="code">
 * &#064;Configuration
 * &#064;EnableAsync
 * public class AppConfig {
 *
 * }</pre>
 *
 * {@code MyAsyncBean} is a user-defined type with one or more methods annotated with
 * either Spring's {@code @Async} annotation, the EJB 3.1 {@code @jakarta.ejb.Asynchronous}
 * annotation, or any custom annotation specified via the {@link #annotation} attribute.
 * The aspect is added transparently for any registered bean, for instance via this
 * configuration:
 *
 * <pre class="code">
 * &#064;Configuration
 * public class AnotherAppConfig {
 *
 *     &#064;Bean
 *     public MyAsyncBean asyncBean() {
 *         return new MyAsyncBean();
 *     }
 * }</pre>
 *
 * <p>By default, Spring will be searching for an associated thread pool definition:
 * either a unique {@link org.springframework.core.task.TaskExecutor} bean in the context,
 * or an {@link java.util.concurrent.Executor} bean named "taskExecutor" otherwise. If
 * neither of the two is resolvable, a {@link org.springframework.core.task.SimpleAsyncTaskExecutor}
 * will be used to process async method invocations. Besides, annotated methods having a
 * {@code void} return type cannot transmit any exception back to the caller. By default,
 * such uncaught exceptions are only logged.
 *
 * <p>To customize all this, implement {@link AsyncConfigurer} and provide:
 * <ul>
 * <li>your own {@link java.util.concurrent.Executor Executor} through the
 * {@link AsyncConfigurer#getAsyncExecutor getAsyncExecutor()} method, and</li>
 * <li>your own {@link org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler
 * AsyncUncaughtExceptionHandler} through the {@link AsyncConfigurer#getAsyncUncaughtExceptionHandler
 * getAsyncUncaughtExceptionHandler()}
 * method.</li>
 * </ul>
 *
 * <p><b>NOTE: {@link AsyncConfigurer} configuration classes get initialized early
 * in the application context bootstrap. If you need any dependencies on other beans
 * there, make sure to declare them 'lazy' as far as possible in order to let them
 * go through other post-processors as well.</b>
 *
 * <pre class="code">
 * &#064;Configuration
 * &#064;EnableAsync
 * public class AppConfig implements AsyncConfigurer {
 *
 *     &#064;Override
 *     public Executor getAsyncExecutor() {
 *         ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
 *         executor.setCorePoolSize(7);
 *         executor.setMaxPoolSize(42);
 *         executor.setQueueCapacity(11);
 *         executor.setThreadNamePrefix("MyExecutor-");
 *         executor.initialize();
 *         return executor;
 *     }
 *
 *     &#064;Override
 *     public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
 *         return new MyAsyncUncaughtExceptionHandler();
 *     }
 * }</pre>
 *
 * <p>If only one item needs to be customized, {@code null} can be returned to
 * keep the default settings.
 *
 * <p>Note: In the above example the {@code ThreadPoolTaskExecutor} is not a fully managed
 * Spring bean. Add the {@code @Bean} annotation to the {@code getAsyncExecutor()} method
 * if you want a fully managed bean. In such circumstances it is no longer necessary to
 * manually call the {@code executor.initialize()} method as this will be invoked
 * automatically when the bean is initialized.
 *
 * <p>For reference, the example above can be compared to the following Spring XML
 * configuration:
 *
 * <pre class="code">
 * &lt;beans&gt;
 *
 *     &lt;task:annotation-driven executor="myExecutor" exception-handler="exceptionHandler"/&gt;
 *
 *     &lt;task:executor id="myExecutor" pool-size="7-42" queue-capacity="11"/&gt;
 *
 *     &lt;bean id="asyncBean" class="com.foo.MyAsyncBean"/&gt;
 *
 *     &lt;bean id="exceptionHandler" class="com.foo.MyAsyncUncaughtExceptionHandler"/&gt;
 *
 * &lt;/beans&gt;
 * </pre>
 *
 * The above XML-based and JavaConfig-based examples are equivalent except for the
 * setting of the <em>thread name prefix</em> of the {@code Executor}; this is because
 * the {@code <task:executor>} element does not expose such an attribute. This
 * demonstrates how the JavaConfig-based approach allows for maximum configurability
 * through direct access to the actual component.
 *
 * <p>The {@link #mode} attribute controls how advice is applied: If the mode is
 * {@link AdviceMode#PROXY} (the default), then the other attributes control the behavior
 * of the proxying. Please note that proxy mode allows for interception of calls through
 * the proxy only; local calls within the same class cannot get intercepted that way.
 *
 * <p>Note that if the {@linkplain #mode} is set to {@link AdviceMode#ASPECTJ}, then the
 * value of the {@link #proxyTargetClass} attribute will be ignored. Note also that in
 * this case the {@code spring-aspects} module JAR must be present on the classpath, with
 * compile-time weaving or load-time weaving applying the aspect to the affected classes.
 * There is no proxy involved in such a scenario; local calls will be intercepted as well.
 *
 * @author Chris Beams
 * @author Juergen Hoeller
 * @author Stephane Nicoll
 * @author Sam Brannen
 * @since 3.1
 * @see Async
 * @see AsyncConfigurer
 * @see AsyncConfigurationSelector
 */
/**
 *启用Spring的异步方法执行功能，类似于功能
 *在Spring的{@code<task:*>}XML命名空间中找到。
 *
 *<p>要与@｛@link Configuration Configuration｝类一起使用，如下所示，
 *为整个Spring应用程序上下文启用注释驱动的异步处理：
 *
 *<pre-class=“code”>
 *&#064；配置
 *&#064；启用异步
 *公共类AppConfig{
 *
 *}</pre>
 *
 *｛@code MyAsyncBean｝是一个用户定义的类型，带有一个或多个用注释的方法
 *Spring的｛@code@Async｝注释、EJB 3.1｛@code@jakarta.EJB.Asynchronous｝
 *注释，或通过{@link#annotation}属性指定的任何自定义注释。
 *该方面对于任何注册的bean都是透明添加的，例如通过
 *配置：
 *
 *<pre-class=“code”>
 *&#064；配置
 *公共类AnotherAppConfig{
 *
 *&#064；豆
 *公共MyAsyncBean异步Bean（）{
 *返回new MyAsyncBean（）；
 *}
 *}</pre>
 *
 *＜p＞默认情况下，Spring将搜索关联的线程池定义：
 *或者是上下文中唯一的{@linkorg.springframework.core.task.Executor}bean，
 *或者一个名为“taskExecutor”的{@link java.util.concurrent.Executor}bean。如果
 *这两者都不可解析，即{@linkorg.springframework.core.task.SimpleAsyncTaskExecutor}
 *将用于处理异步方法调用。此外，具有
 *｛@code void｝返回类型无法将任何异常传输回调用方。默认情况下，
 *只记录此类未捕获的异常。
 *
 *＜p＞若要自定义所有这些，请实现｛@link AsyncConfigurer｝并提供：
 *<ul>
 *<li>通过
 *｛@link AsyncConfigurer#getAsyncExecutior getAsyncExecutor（）｝方法，以及</li>
 *<li>您自己的｛@link org.springframework.aop.interceptor.AsyncUncaughtException处理程序
 *AsyncUnaughtException Handler｝通过｛@link AsyncConfigurer#getAsyncUncaughtException Handler
 *getAsyncUncaughtException处理程序（）｝
 *方法</li>
 *</ul>
 *
 *<p><b>注意：｛@link AsyncConfigurer｝配置类提前初始化
 *在应用程序上下文引导中。如果您需要依赖其他bean
 *在那里，一定要尽可能地宣布他们“懒惰”，以便让他们
 *也要通过其他后处理程序</b>
 *
 *<pre-class=“code”>
 *&#064；配置
 *&#064；启用异步
 *公共类AppConfig实现AsyncConfigurer{
 *
 *&#064；以（权力）否决
 *公共执行程序getAsyncExecutor（）{
 *ThreadPoolTaskExecutior-executor=新的ThreadPoolTaskExecutor（）；
 *executor.setCorePoolSize（7）；
 *executor.setMaxPoolSize（42）；
 *executor.setQueueCapacity（11）；
 *executor.setThreadNamePrefix（“MyExecutor-”）；
 *executor.initialize（）；
 *返还执行人；
 *}
 *
 *&#064；以（权力）否决
 *公共异步未捕获异常处理程序getAsyncUnaughtException处理程序（）{
 *返回新的MyAsyncUncaughtException Handler（）；
 *}
 *}</pre>
 *
 *＜p＞如果只需要自定义一个项目，则可以将｛@code null｝返回到
 *保留默认设置。
 *
 *＜p＞注意：在上面的示例中，｛@code ThreadPoolTaskExecutitor｝不是完全托管的
 *春豆。将｛@code@Bean｝注释添加到｛@code getAsyncExecutor（）｝方法
 *如果您想要一个完全管理的bean。在这种情况下，不再需要
 *手动调用｛@code executor.initialize（）｝方法，因为它将被调用
 *在初始化bean时自动执行。
 *
 *＜p＞为了参考，上面的例子可以与下面的Spring XML进行比较
 *配置：
 *
 *<pre-class=“code”>
 *&lt；豆子&gt；
 *
 *&lt；任务：注释驱动的executor=“myExecutor”异常处理程序=“exceptionHandler”/&gt；
 *
 *&lt；task:executor id=“myExecutor”池大小=“7-42”队列容量=“11”/&gt；
 *
 *&lt；bean id=“asyncBean”class=“com.foo.MyAsyncBean”/&gt；
 *
 *&lt；bean id=“exceptionHandler”class=“com.foo.MyAsyncUnaughtException Handler”/&gt；
 *
 *&lt/豆子&gt；
 *</pre>
 *
 *除了
 *设置{@code Executor}的<em>线程名称前缀</em>；这是因为
 *{@code<task:executor>}元素不公开这样的属性。这
 *演示了基于JavaConfig的方法如何实现最大的可配置性
 *通过直接访问实际组件。
 *
 *＜p＞｛@link#mode｝属性控制建议的应用方式：如果模式为
 *｛@link AdviceMode#PROXY｝（默认值），然后其他属性控制行为
 *代理。请注意，代理模式允许通过
 *仅限代理人；同一类中的本地调用不能以这种方式被截获。
 *
 *<p>请注意，如果｛@linkplain#模式｝设置为｛@link AdviceMode#ASPECTJ｝，则
 *｛@link#proxyTargetClass｝属性的值将被忽略。还要注意，在
 *在这种情况下，{@codespring-aspects}模块JAR必须存在于类路径中
 *编译时编织或加载时编织将方面应用于受影响的类。
 *在这种情况下没有代理；本地呼叫也将被截获。
 *
 *@作者Chris Beams
 *@作者于尔根·霍勒
 *@作者Stephane Nicoll
 *@作者Sam Brannen
 *@自3.1起
 *@参见异步
 *@请参阅AsyncConfigurer
 *@请参阅AsyncConfigurationSelector
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {

	/**
	 * Indicate the 'async' annotation type to be detected at either class
	 * or method level.
	 * <p>By default, both Spring's @{@link Async} annotation and the EJB 3.1
	 * {@code @jakarta.ejb.Asynchronous} annotation will be detected.
	 * <p>This attribute exists so that developers can provide their own
	 * custom annotation type to indicate that a method (or all methods of
	 * a given class) should be invoked asynchronously.
	 */
	/**
	 *指示要在任一类中检测到的“async”注释类型
	 *或方法级别。
	 *＜p＞默认情况下，Spring的@｛@link Async｝注释和EJB 3.1
	 *｛@code@jakarta.ejb.Asynchronous｝注释将被检测到。
	 *<p>此属性的存在使开发人员可以提供自己的
	 *自定义注释类型，以指示
	 *给定的类）应该异步调用。
	 */
	Class<? extends Annotation> annotation() default Annotation.class;

	/**
	 * Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
	 * to standard Java interface-based proxies.
	 * <p><strong>Applicable only if the {@link #mode} is set to {@link AdviceMode#PROXY}</strong>.
	 * <p>The default is {@code false}.
	 * <p>Note that setting this attribute to {@code true} will affect <em>all</em>
	 * Spring-managed beans requiring proxying, not just those marked with {@code @Async}.
	 * For example, other beans marked with Spring's {@code @Transactional} annotation
	 * will be upgraded to subclass proxying at the same time. This approach has no
	 * negative impact in practice unless one is explicitly expecting one type of proxy
	 * vs. another &mdash; for example, in tests.
	 */
	/**
	 *指示是否创建基于子类的（CGLIB）代理
	 *到标准的基于Java接口的代理。
	 *<p><strong>仅当｛@link#模式｝设置为｛@link AdviceMode#PROXY｝时适用</strong>。
	 *＜p＞默认值为｛@code false｝。
	 *＜p＞请注意，将此属性设置为｛@code true｝将影响＜em＞所有</em>
	 *Spring管理的bean需要代理，而不仅仅是那些用{@code@anc}标记的bean。
	 *例如，用Spring的{@code@Transactional}注释标记的其他bean
	 *将同时升级为子类代理。这种方法没有
	 *实践中的负面影响，除非明确期望使用一种类型的代理
	 *与另一个相比&mdash；例如在测试中。
	 */
	boolean proxyTargetClass() default false;

	/**
	 * Indicate how async advice should be applied.
	 * <p><b>The default is {@link AdviceMode#PROXY}.</b>
	 * Please note that proxy mode allows for interception of calls through the proxy
	 * only. Local calls within the same class cannot get intercepted that way; an
	 * {@link Async} annotation on such a method within a local call will be ignored
	 * since Spring's interceptor does not even kick in for such a runtime scenario.
	 * For a more advanced mode of interception, consider switching this to
	 * {@link AdviceMode#ASPECTJ}.
	 */
	/**
	 *指示应如何应用异步建议。
	 *<p><b>默认值为｛@link AdviceMode#PROXY｝</b>
	 *请注意，代理模式允许通过代理拦截呼叫
	 *只有。同一类中的本地呼叫不能以这种方式被拦截；一
	 *本地调用中对此类方法的｛@link Async｝注释将被忽略
	 *因为Spring的拦截器甚至不适用于这样的运行时场景。
	 *对于更高级的拦截模式，请考虑将其切换为
	 *｛@link建议模式#ASPECTJ｝。
	 */
	AdviceMode mode() default AdviceMode.PROXY;

	/**
	 * Indicate the order in which the {@link AsyncAnnotationBeanPostProcessor}
	 * should be applied.
	 * <p>The default is {@link Ordered#LOWEST_PRECEDENCE} in order to run
	 * after all other post-processors, so that it can add an advisor to
	 * existing proxies rather than double-proxy.
	 */
	/**
	 *指示｛@link AsyncAnnotationBeanPostProcessor｝的顺序
	 *应该应用。
	 *＜p＞默认值为｛@link Ordered#LOWEST_PRECDENCE｝，以便运行
	 *在所有其他后处理器之后，这样它就可以将顾问添加到
	 *现有代理，而不是双重代理。
	 */
	int order() default Ordered.LOWEST_PRECEDENCE;

}
